package com.ndood;
import java.util.Optional;

import javax.annotation.PostConstruct;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

import com.ndood.reconciliation.app.redis.ReconRedisTool;
import com.ndood.reconciliation.app.redis.RedisReconKeyHelper;
import com.ndood.reconciliation.base.enums.EnumPayway;
import com.ndood.reconciliation.base.util.MetricsUtil;
import com.ndood.reconciliation.domain.recon.entity.dto.ReconInfoDto;
import com.ndood.reconciliation.domain.recon.service.ReconAlipayOfflineService;

import lombok.extern.slf4j.Slf4j;

@SpringBootApplication
@EnableScheduling
@MapperScan({"com.ndood.*.base.dao"})
@Slf4j
public class ReconApplication {

	@Autowired
	private ReconRedisTool reconRedisTool;
	
	/**
	 * 目前只支持离线方式对账
	 */
	@Autowired
	private ReconAlipayOfflineService  alipayOfflineReconService;
	
	/**
	 * 控制线程启动关闭
	 */
	private boolean flag = true;
	
    public static void main(String[] args) {
        SpringApplication.run(ReconApplication.class, args);
    }
    
	@PostConstruct
    public void init() {
        startThead();
    }

	private void startThead() {
		for (int i = 0; i < MetricsUtil.CONCURRENCY; i++) {
			final int finalI = i;
			MetricsUtil.m(() -> {
				log.info("CheckService start, thread: " + finalI);
				while (flag ) {
					try {
						// Step1: 从队列中获取一个任务，如果没有任务，则从缓存队列取
						Optional<String> optReconKey = reconRedisTool.spopKeyFromSnapchat();
						if (!optReconKey.isPresent()) {
							reconRedisTool.createSnapchat();
							Thread.sleep(500);
							continue;
						}
						// Step2: 对任务加锁，如果没获取到锁则将任务加到缓存队列末尾
						String reconKey = optReconKey.get();
						boolean lock = reconRedisTool.tryLock(reconKey, 5l);
						if(!lock) {
							reconRedisTool.saddKey(reconKey);
							Thread.sleep(500);
							continue;
						}
						
						// Step3: 处理批量检查任务，处理完后释放锁
						try {
							ReconInfoDto reconInfo = RedisReconKeyHelper.getReconInfo(reconKey);
							if(EnumPayway.ALIPAY.equals(reconInfo.getPayway())) {
								alipayOfflineReconService.doWithReconciliation(reconInfo);
							}
						} catch (Exception e){
							throw e;
						} finally {
							reconRedisTool.realseLock(reconKey);
						}
						
					} catch (Exception e) {
						log.error(e.getMessage(), e);
					}
				}
				log.info("ServiceHandler unicast end, thread: " + finalI);
			});
		}
	}
    
}
